#include "pro.h"


const float center1=40, center2=43, sigma2=2;

/** The First Function **/
int ImageIntensityDistribution(float* imageIntensity,
			       float* imageLocation,
			       int imageLength,
			       bool isOutputFile) {
	
    int i=1;
    do {
	imageLocation[i-1] = i;

	//Add source1
	imageIntensity[i-1] = exp(-(i-center1)*(i-center1)/sigma2);

	//Add source2
	imageIntensity[i-1] += exp(-(i-center2)*(i-center2)/sigma2);

	i++;
    } while (i<=imageLength);

    //Output to file.
    if (isOutputFile) {

	ofstream file1("Intensity.txt");
	if (!file1) {
	    cout << "File Open ERROR" << endl;
	    return 0;
	}
	
	for (i=0;i<imageLength;i++) {
	    file1 << *(imageLocation+i);
	    file1 << " " ;
	    file1 << *(imageIntensity+i);
	    file1 << "\n";
	}
	file1.close();

    }

    return 1;
}

/** The First Function Different image **/
int IID2(float* imageIntensity,
	 float* imageLocation,
	 int imageLength,
	 bool isOutputFile) {
	
    int i=1;
    do {
	imageLocation[i-1] = i;

	i++;
    } while (i<=imageLength);

    //Add source1
    imageIntensity[int(center1)-1] = 1;

    //Add source2
    imageIntensity[int(center2)-1] = 1;

    //Output to file.
    if (isOutputFile) {

	ofstream file1("Intensity.txt");
	if (!file1) {
	    cout << "File Open ERROR" << endl;
	    return 0;
	}
	
	for (i=0;i<imageLength;i++) {
	    file1 << *(imageLocation+i);
	    file1 << " " ;
	    file1 << *(imageIntensity+i);
	    file1 << "\n";
	}
	file1.close();

    }

    return 1;
}

/** The Second Function **/
int SourceSignalGeneration(float* signal,
			   float* imageIntensity,
			   float* imageLocation,
			   int imageLength,
			   float samplingDistance,
			   int coherentLength,
			   int numberOfSignal,
			   bool isOutputFile) {


	
    int m = numberOfSignal/coherentLength;
    float* random=new float[m];  
    //The generated random numbers will be saved in this array.

    int i,j,k;

    //Intialize the random number generator.
    srand( (unsigned int)time(NULL) );
    for (j=0;j<imageLength;j++) {

	//There is a big problem here. 
	//Since time() return the time in unit of second,
	//and this function will be finished within a second,
	//so all random number will be same.
	//srand( (unsigned int)time(NULL) );
	for (k=0;k<m;k++) {
	    random[k]=( (float)rand()/RAND_MAX-0.5);
	    //The value of random number will between -0.5 and 0.5
			
	    for (i=0;i<coherentLength;i++) {
		*( signal+numberOfSignal*j + k*coherentLength + i) =
		    random[k]*imageIntensity[j];
	    }
	}
    }

    //Output to file.
    if (isOutputFile) {

	ofstream file2("signal.txt");
	if (!file2) {
	    cout << "File Open ERROR" << endl;
	    return 0;
	}

	for (k=0;k<numberOfSignal;k++) {
	    for (j=0;j<imageLength;j++) {	
		file2 << *( signal+numberOfSignal*j + k) << " ";
	    }
	    file2 << "\n";
	}

	file2.close();
    }

    delete random;
    return 1;
}

/** The third function **/
int DelayMatrix(float* delay,
		float* imageLocation,
		int imageLength,
		float* detectorLocation,
		int numberOfDetector,
		float distance,
		bool isOutputFile) {

    int i,j;

    //Calculate the path.
    for (i=0;i<numberOfDetector;i++) {
	for (j=0;j<imageLength;j++) {
	    *(delay + imageLength*i + j) = 
		sqrt( distance*distance + (*(detectorLocation+i)-(j+1))* 
		      (*(detectorLocation+i)-(j+1)) );

	}
    }

    if (isOutputFile) {

	ofstream file3("DelayMatrix.txt");
	// Output file.
	if (!file3) {
	    cout << "File Open ERROR";
	    return 0;
	}

	for (i=0;i<numberOfDetector;i++) {
	    file3 << *(detectorLocation+i) << " ";
	    for (j=0;j<imageLength;j++) {
		file3 << *(delay+imageLength*i+j) << " ";
	    }
	    file3 << "\n";
	}
	file3.close();
    }

    return 1;
}

/** The fourth function **/
int RecievedSignalGeneration(float* receivedSignal,
			     float* signal,
			     float* delay,
			     int imageLength,
			     int numberOfDetector,
			     float samplingDistance,
			     int numberOfReceivedSignal,
			     float* detectorLocation,
			     int numberOfSignal,
			     int distance,
			     int coherentLength,
			     bool isOutputFile) {

    /* Calculate the signal */
 	
    int m = numberOfSignal/coherentLength;

    int i,j,k,z=0;
    float *p;

    //Find the maximum optical path of ith receiver.
    //We also need to find the maximum optical path for 
    //all receivers. Therefore, we can use it to synchronize
    //the signals.    
    float maxdistance=0, mindistance=1.0e18;
    for (i=0;i<numberOfDetector;i++) {
	for (j=0;j<imageLength;j++) {
	    p = delay+i*imageLength+j;
	    if (*p>maxdistance) maxdistance = *p;
	    if (*p<mindistance) mindistance = *p;
	}
    }	

    m = int((maxdistance-mindistance)/samplingDistance);
    z = numberOfSignal - m;
    if (z>numberOfReceivedSignal) {
	cout << "z=" << z << " exceed ";
	z = numberOfReceivedSignal;
	cout << numberOfReceivedSignal << endl;
    } else {
	cout << "numberOfReceivedSignal ERROR" << endl;
	return 0;
    }

    /* Calculate float* receivedSignal */	
    for (i=0;i<numberOfDetector;i++) {
		
	// Superposition of the signal.
	for (j=0;j<z;j++) {
	    for (k=0;k<imageLength;k++) {
				
		m = (int)( (maxdistance - *(delay+i*imageLength+k))
			  /samplingDistance)+j;
		p = receivedSignal + i*z + j;
		*p = *p + *(signal+k*numberOfSignal+m);
	    }
	}
		
    }
	
    if (isOutputFile) {

	ofstream file4("ReceivedSignal.txt");
	if (!file4) {
	    cout << "File Open ERROR";
	    return 0;
	}
	

	for (i=0;i<numberOfDetector;i++) {
	    file4 << *(detectorLocation+i) << " ";
	}

	file4 << "\n";

	for (j=0;j<z;j++) {
	    for (i=0;i<numberOfDetector;i++) {
		file4 << *(receivedSignal+i*numberOfReceivedSignal+j)
		      << " ";
	    }
	    file4 << "\n";
	}
		
	file4.close();

    }

    return 1;

}

/** The fifth function **/
int HolographicImaging(float* image, 
		       float* imageLocation, 
		       int imageLength,
		       float* receivedSignal,
		       int numberOfDetector,
		       int numberOfReceivedSignal,
		       float* detectorLocation,
		       float samplingDistance,
		       float distance5,
		       float* delay,
		       int coherentLength,
		       int numberOfSignal,
		       bool isOutputFile) {

    int i, j, k, l, p;

    /* The realization of fifth function */
    int n_two = numberOfDetector*(numberOfDetector-1)/2;     

    int ndD;         //ndD, step of realignment.
    float dD,sumLR;  //sumLR is used for save summed values.
    float pL, pR;    //Temporary optical path.
    float rs1, rs2;  //Temporary values for received signals.
    int npLdD, npRdD; 

    //Initialize image.
    for (i=0;i<imageLength;i++) image[i]=0;

    //Obtain the image.
    for (i=0;i<imageLength;i++) {

	for (j=0;j<numberOfDetector;j++) {
	    for (k=j+1;k<numberOfDetector;k++) {
		pL = delay[imageLength*j + i];
		pR = delay[imageLength*k + i];
		dD = abs(pL-pR);

		// Calculate the optical path delay between two receivers.
		ndD=(int)(dD/samplingDistance);

		if (pL>pR) { 
		    npLdD = ndD;
		    npRdD = 0;
		} else {
		    npLdD = 0;
		    npRdD = ndD;
		}

		sumLR = 0.0;
		//Correlate the received signals.
		for (p=0;p<(numberOfReceivedSignal-ndD);p++) {
		    rs1 = receivedSignal[j*numberOfReceivedSignal + p + npLdD];
		    rs2 = receivedSignal[k*numberOfReceivedSignal + p + npRdD];
		    sumLR += rs1*rs2;
		}

		//Average the sumLR.
		sumLR /= float(numberOfReceivedSignal-ndD);

		//Add the image
		image[i] += sumLR;
	    }
	}

	//Average the image.
	image[i] /= n_two;
    }


    if (isOutputFile) {

	//Output image to a file.				
	ofstream file5("Newimage.txt");
	if (!file5) {
	    cout << "File Open ERROR!";
	    return 0;
	}
	
	for (i=0;i<imageLength;i++) {
	    file5 << imageLocation[i];
	    file5 << " ";
	    file5 << image[i];
	    file5 << "\n";
	}
	file5.close();
    }

    return 1;
} 
